package mgo

import (
	"gopkg.in/mgo.v2"
	"mime/multipart"
	"crypto/md5"
	"io"
	"encoding/hex"
	"net/http"
	"image/jpeg"
	"image/png"
	"image/gif"
	"github.com/nfnt/resize"
	"image"
	"hub.hddznet.com/app/midway_app/errors"
	"fmt"
	"strings"
)

type MgoFs struct {
	*mgo.GridFS
}

// 上传文件
func (this *MgoFs) HDUploadScada6(name string, contentType string, file multipart.File) (string, error) {
	hash := md5.New()
	io.Copy(hash, file)

	file.Seek(0, io.SeekStart)
	md5hash := hex.EncodeToString(hash.Sum([]byte("")))

	id := "/upload/" + md5hash[0:1] + "/" + md5hash[0:2] + "/" + md5hash + name[strings.Index(name, "."):]
	f, err := this.OpenId(id)

	if err != nil && err != mgo.ErrNotFound {
		return "", err
	}

	if f != nil && f.Size() > 0 {
		defer f.Close()
		return id, nil
	}

	f, err = this.Create(md5hash)

	f.SetId(id)
	f.SetName(name)
	f.SetContentType(contentType)

	defer f.Close()
	if err != nil {
		return "", err
	}
	if _, err := io.Copy(f, file); err != nil {
		return "", err
	}
	return id, err
}

// 上传文件(未测试有效)
func (this *MgoFs) HDUploadScada7(name string, contentType string, file multipart.File) (string, error) {
	hash := md5.New()
	io.Copy(hash, file)

	file.Seek(0, io.SeekStart)
	md5hash := hex.EncodeToString(hash.Sum([]byte("")))

	id := md5hash
	f, err := this.OpenId(id)

	if err != nil && err != mgo.ErrNotFound {
		return "", err
	}

	if f != nil && f.Size() > 0 {
		defer f.Close()
		return id, nil
	}

	f, err = this.Create(md5hash)

	f.SetId(id)
	f.SetName(name)
	f.SetContentType(contentType)

	defer f.Close()
	if err != nil {
		return "", err
	}
	if _, err := io.Copy(f, file); err != nil {
		return "", err
	}
	return id, err
}

type LikeFile interface {
	io.ReadWriteSeeker
	io.Closer
}

//读取文件
func (this *MgoFs) HDGet(hex string) ([]byte, error) {
	f, err := this.OpenId(hex)
	if err != nil {
		return nil, errors.FsGetErr(err)
	}
	data := make([]byte, f.Size())
	f.Read(data)
	f.Close()
	return data, nil
}

//文件压缩
func (this *MgoFs) HDResize(hex string, width int, height int) (io.ReadCloser, error) {

	sid := fmt.Sprintf("%s/%d/%d", hex, width, height)
	o, err := this.OpenId(sid)

	if err == nil {
		return o, nil
	}

	f, err := this.OpenId(hex)

	b := make([]byte, 512)
	f.Read(b)
	mime := http.DetectContentType(b)
	f.Seek(0, io.SeekStart)

	defer f.Close()

	if err != nil {
		return nil, err
	}

	var img image.Image

	img, _, err = image.Decode(f)

	if err != nil {
		return nil, err
	}

	m := resize.Thumbnail(uint(width), uint(height), img, resize.MitchellNetravali)

	i, err := this.Create(sid)
	i.SetId(sid)

	if err != nil {
		return nil, err
	}

	switch mime {
	case "image/jpg", "image/jpeg":
		if err := jpeg.Encode(i, m, nil); err != nil {
			i.Close()
			return nil, err
		}
	case "image/png":
		if err := png.Encode(i, m); err != nil {
			i.Close()
			return nil, err
		}
	case "image/gif":
		if err := gif.Encode(i, m, nil); err != nil {
			i.Close()
			return nil, err
		}
	default:
		return nil, errors.FsFileTypeErr(mime)
	}

	i.Close()

	i, err = this.OpenId(i.Id())

	if err != nil {
		return nil, err
	}

	return i, nil
}

//获取文件宽高
func (this *MgoFs) HDSize(hex string) (width int, height int, err error) {

	f, err := this.OpenId(hex)

	if err != nil {
		return 0, 0, err
	}

	defer f.Close()

	c, _, err := image.DecodeConfig(f)

	if err != nil {
		return
	}

	return c.Width, c.Height, err
}
